//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "STUNEShop.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
#include "Shop.h"
//---------------------------------------------------------------------------
TForm_Shop *Form_Shop;
Shop* shop = NULL; // pointer for the shop object
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// ADO database functions

// check the shop
bool checkShop(AnsiString shopId, AnsiString &shopName)
{
	/*	shopName = "stune";       temp ayush comment
	return true;  */
	//*****
	
	AnsiString query = "select shop_name from shops where shop_id = "+shopId; // prepare query
	Form_Shop->ADOQueryDB->SQL->Clear(); // clear the previous ado query
	Form_Shop->ADOQueryDB->SQL->Add(query); // add the query to the ado
	try // try to query the database
	{
		Form_Shop->ADOQueryDB->Open(); // open the query
		if (Form_Shop->ADOQueryDB->Eof) // check if there is a result
		{
			return false;	// there were no rows; no result
		}
		shopName = Form_Shop->ADOQueryDB->FieldByName("shop_name")->AsString; // store the result
		Form_Shop->ADOQueryDB->Close(); // close the query
		return true; // query was succesfull
	}
	catch  (Exception &err)
	{
		return false; // there was an error
	}
}

// get the stock from the database
bool getStock(AnsiString shopId)
{
	/*shop->addArticle(1, "Coca-Cola", 250, "Drinks", 2.5, 0);     temp ayush comment
	shop->addArticle(2, "Fanta", 120, "Drinks", 2.5, 0);
	shop->addArticle(3, "Hamburger", 200, "Snack", 5, 0);
	return true; */
	//****

	AnsiString nm, kd; int id, qt; double pr, dp; // temp variables

	AnsiString query = "SELECT articles.article_id,name,price,kind,deposite,quantity FROM articles_in_shops, articles WHERE articles.article_id=articles_in_shops.article_id AND deposite IS NULL AND shop_id="+shopId; // prepare query
	Form_Shop->ADOQueryDB->SQL->Clear(); // clear the previous ado query
	Form_Shop->ADOQueryDB->SQL->Add(query); // add the query to the ado
	try // try to query the database
	{
		Form_Shop->ADOQueryDB->Open(); // open the query
		if (Form_Shop->ADOQueryDB->Eof) // check if there is a result
		{
			return false;	// there were no rows; no result
		}
		while (!Form_Shop->ADOQueryDB->Eof) // loop through all the rows; all results
		{
			id = Form_Shop->ADOQueryDB->FieldByName("article_id")->AsInteger; // store the result
			nm = Form_Shop->ADOQueryDB->FieldByName("name")->AsString; // store the result
			qt = Form_Shop->ADOQueryDB->FieldByName("quantity")->AsInteger; // store the result
			kd = Form_Shop->ADOQueryDB->FieldByName("kind")->AsString; // store the result
			pr = Form_Shop->ADOQueryDB->FieldByName("price")->AsFloat; // store the result
			dp = Form_Shop->ADOQueryDB->FieldByName("deposite")->AsFloat; // store the result
			shop->addArticle(id, nm, qt, kd, pr, dp); // add the article to the shop
			Form_Shop->ADOQueryDB->Next();// go to next row
        }
		Form_Shop->ADOQueryDB->Close(); // close the query
		return true; // query was succesfull
	}
	catch  (Exception &err)
	{
		return false; // there was an error
	}
}

// decrease the stock of the shop
bool decreaseStock()
{
	
   //	return true;
	//****
	
	for (int i = 0; i < shop->getNrOfPurchases(); i++)
	{
		AnsiString query = "update articles_in_shops set quantity = quantity-"+AnsiString(shop->getPurchaseQtAtIndex(i))+" where article_id = "+AnsiString(shop->getPurchaseIdAtIndex(i))+" and shop_id = "+shop->getID(); // prepare query
		Form_Shop->ADOQueryDB->SQL->Clear(); // clear the previous ado query
		Form_Shop->ADOQueryDB->SQL->Add(query); // add the query to the ado
		try // try to query the database
		{
			Form_Shop->ADOQueryDB->ExecSQL(); // do the update query
			Form_Shop->ADOQueryDB->Close();
		}
		catch  (Exception &err)
		{
			return false; // there was an error
		}
	}
	return true; // query was succesfull
}

// get the balance of the guest
bool getBalance(AnsiString guestId, double &balance)
{
	 /*	if (guestId == "1234")
	{
		balance = 40;
		return true;
	}
	return false; */
	//****
	
	AnsiString query = "select balance from guests where guest_id = "+guestId; // prepare query
	Form_Shop->ADOQueryDB->SQL->Clear(); // clear the previous ado query
	Form_Shop->ADOQueryDB->SQL->Add(query); // add the query to the ado
	try // try to query the database
	{
		Form_Shop->ADOQueryDB->Open(); // open the query
		if (Form_Shop->ADOQueryDB->Eof) // check if there is a result
		{
			return false;	// there were no rows; no result
		}
		balance = Form_Shop->ADOQueryDB->FieldByName("balance")->AsFloat; // store the result
		Form_Shop->ADOQueryDB->Close(); // close the query
		return true; // query was succesfull
	}
	catch  (Exception &err)
	{
		return false; // there was an error
	}
}

// decrease the balance of the guest
bool decreaseBalance(AnsiString guestId, double total)
{
//	return true;
	//****

   AnsiString query = "update guests set balance = balance-"+AnsiString(total)+" where guest_id = "+guestId; // prepare query
   //AnsiString query = "update guests set balance = balance-1 where guest_id = "+guestId;
	Form_Shop->ADOQueryDB->SQL->Clear(); // clear the previous ado query
	Form_Shop->ADOQueryDB->SQL->Add(query); // add the query to the ado
	try // try to query the database
	{
		Form_Shop->ADOQueryDB->ExecSQL(); // do the update query
		Form_Shop->ADOQueryDB->Close();
		return true; // query was succesfull
	}
	catch  (Exception &err)
	{
		return false; // there was an error
	}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
AnsiString padRight(AnsiString str, int len)
{
	if (str.Length() < len)
	{
		return str+AnsiString().StringOfChar(' ', len-str.Length());
	}
	else
	{
		return str+" ";
	}
}

void updateInfo()
{
	// show some info
		// check the total...
	if (!Form_Shop->edtQuantity->Text.IsEmpty())
	{
		if (Form_Shop->ListOfStocks->ItemIndex != -1)
		{
			if (Form_Shop->edtQuantity->Text.ToInt() > shop->getArticleAtIndex(Form_Shop->ListOfStocks->ItemIndex)->getNrOfItems())
			{
				Form_Shop->edtQuantity->Text = AnsiString(shop->getArticleAtIndex(Form_Shop->ListOfStocks->ItemIndex)->getNrOfItems());
			}
		}
		else if (Form_Shop->ListPurchase->ItemIndex != -1)
		{
			if (Form_Shop->edtQuantity->Text.ToInt() > shop->getPurchaseQtAtIndex(Form_Shop->ListPurchase->ItemIndex))
			{
				Form_Shop->edtQuantity->Text = AnsiString(shop->getPurchaseQtAtIndex(Form_Shop->ListPurchase->ItemIndex));
			}
		}
	}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// this function shows all articles in the listbox ListOfStock
void showAllArticles()
{
	Form_Shop->ListOfStocks->Clear();		// clear the listbox
	// show all the articles
	for (int index = 0; index < shop->getNrOfArticles(); index++)
	{
			// Show the content of article in listbox.
			Form_Shop->ListOfStocks->Items->Add(shop->getArticleAtIndex(index)->asAString());
	}
}
//---------------------------------------------------------------------------
void showAllPurchases()
{
	Form_Shop->ListPurchase->Clear();		// clear the listbox
	// show all the purchases
	for (int index = 0; index < shop->getNrOfPurchases(); index++)
	{
			// Show the content of purchase in listbox.
			int qt = shop->getPurchaseQtAtIndex(index);			// get the quantity
			AnsiString temp = padRight(AnsiString(qt)+"x", 6);              // show quantity
			temp += padRight(shop->getPurchaseAtIndex(index)->getName(), 18); // show name
			temp += AnsiString().FormatFloat("0.00", shop->getPurchaseAtIndex(index)->getPrice()*qt); // show total price
			Form_Shop->ListPurchase->Items->Add(temp); 			// show the info in listbox
	}
}
//---------------------------------------------------------------------------
// this function shows a error to the user
void ShowError(AnsiString error)
{
    ShowMessage(error);
}
//---------------------------------------------------------------------------
__fastcall TForm_Shop::TForm_Shop(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm_Shop::btnOpenShopClick(TObject *Sender)
{
	/*
	   1. create a shop or if the shop is already created, delete the shop.
	   2. when shop created, make the editbox become disabled and change
		  this button to close shop.
	   3. when the shop is deleted, make the editbox become enabled and change
		  this button to open shop.
	*/

	if (shop == NULL) // if there is no shop
	{
		if (!this->edtShopID->Text.IsEmpty()) // check shop name is not empty
		{
			AnsiString tempName = "";
			if (checkShop(this->edtShopID->Text, tempName))
			{
				shop = new Shop(this->edtShopID->Text, tempName); //create a new shop

				this->btnOpenShop->Caption = "Close Shop"; //change the button text
				this->edtShopID->Text = tempName;  // show the name instead of id
				this->edtShopID->Enabled = false;  // disable the edit box

				getStock(shop->getID());	   	   // get the stock
				shop->sortAllArticlesByName();// sort the stock by name first
				showAllArticles(); 		// next we show the articles

				// enable actions
				this->edtGuestId->Enabled = true;
				this->edtQuantity->Enabled = true;
				this->btnAdd->Enabled = true;
				this->btnCancel->Enabled = true;
				this->btnConfirm->Enabled = true;
				this->btnRemove->Enabled = true;
				this->btnSortKind->Enabled = true;
				this->btnSortName->Enabled = true;
				this->btnSortPrice->Enabled = true;
				this->ListOfStocks->Enabled = true;
				this->ListPurchase->Enabled = true;
			}
			else
			{
				ShowMessage("Shop ID not found!");
			}
		}
		else // is shop name empty show a error message
		{
			ShowError("Please type a shop name!");
		}
	}
	else // shop exists
	{
		delete shop;         //delete the shop
		shop = NULL;         //make the pointer equals null
		this->btnOpenShop->Caption = "Open Shop";  // change the button text
		this->edtShopID->Enabled = true;       // enable the edit box
		this->edtShopID->Clear();              // clear edit box
		this->ListOfStocks->Clear();   		   // clear the stock list
		this->ListPurchase->Clear();           // clear the purchase list
		this->edtQuantity->Clear();			   // clear the quantity
		this->edtGuestId->Clear();			   // clear the guest id
		this->lblTotal->Caption = "0.00";	   // reset the total price
		this->lblPurchaseInfo->Caption = "";   // reset the purchase info

		// disable actions
		this->edtGuestId->Enabled = false;
		this->edtQuantity->Enabled = false;
		this->btnAdd->Enabled = false;
		this->btnCancel->Enabled = false;
		this->btnConfirm->Enabled = false;
		this->btnRemove->Enabled = false;
		this->btnSortKind->Enabled = false;
		this->btnSortName->Enabled = false;
		this->btnSortPrice->Enabled = false;
		this->ListOfStocks->Enabled = false;
		this->ListPurchase->Enabled = false;
	}                                     if (shop == NULL) // if there is no shop
	{
		if (!this->edtShopID->Text.IsEmpty()) // check shop name is not empty
		{
			AnsiString tempName = "";
			if (checkShop(this->edtShopID->Text, tempName))
			{
				shop = new Shop(this->edtShopID->Text, tempName); //create a new shop

				this->btnOpenShop->Caption = "Close Shop"; //change the button text
				this->edtShopID->Text = tempName;  // show the name instead of id
				this->edtShopID->Enabled = false;  // disable the edit box

				getStock(shop->getID());	   	   // get the stock
				shop->sortAllArticlesByName();// sort the stock by name first
				showAllArticles(); 		// next we show the articles

				// enable actions
				this->edtGuestId->Enabled = true;
				this->edtQuantity->Enabled = true;
				this->btnAdd->Enabled = true;
				this->btnCancel->Enabled = true;
				this->btnConfirm->Enabled = true;
				this->btnRemove->Enabled = true;
				this->btnSortKind->Enabled = true;
				this->btnSortName->Enabled = true;
				this->btnSortPrice->Enabled = true;
				this->ListOfStocks->Enabled = true;
				this->ListPurchase->Enabled = true;
			}
			else
			{
				ShowMessage("Shop ID not found!");
			}
		}
		else // is shop name empty show a error message
		{
			ShowError("Please type a shop name!");
		}
	}
	else // shop exists
	{
		delete shop;         //delete the shop
		shop = NULL;         //make the pointer equals null
		this->btnOpenShop->Caption = "Open Shop";  // change the button text
		this->edtShopID->Enabled = true;       // enable the edit box
		this->edtShopID->Clear();              // clear edit box
		this->ListOfStocks->Clear();   		   // clear the stock list
		this->ListPurchase->Clear();           // clear the purchase list
		this->edtQuantity->Clear();			   // clear the quantity
		this->edtGuestId->Clear();			   // clear the guest id
		this->lblTotal->Caption = "0.00";	   // reset the total price
		this->lblPurchaseInfo->Caption = "";   // reset the purchase info

		// disable actions
		this->edtGuestId->Enabled = false;
		this->edtQuantity->Enabled = false;
		this->btnAdd->Enabled = false;
		this->btnCancel->Enabled = false;
		this->btnConfirm->Enabled = false;
		this->btnRemove->Enabled = false;
		this->btnSortKind->Enabled = false;
		this->btnSortName->Enabled = false;
		this->btnSortPrice->Enabled = false;
		this->ListOfStocks->Enabled = false;
		this->ListPurchase->Enabled = false;
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm_Shop::btnAddClick(TObject *Sender)
{
	/*
	   1. get the index of the item in stock list
	   2. add button will remove item from stock list and add to purchase list
	   3. check if there is enough stock to be remove
	   4. increase the total price
	*/
	int index = this->ListOfStocks->ItemIndex;
	if (index != -1)   // if stock item selected
	{
		if (!this->edtQuantity->Text.IsEmpty())// check edit quantity is not empty
		{
		  /*
			 1. get article id
			 2.	sell the article
		  */
		  int id = shop->getArticleAtIndex(index)->getArticleID();	// get article id
		  if (shop->soldSome(id, this->edtQuantity->Text.ToInt()) == true)
		  {
		      // refresh listbox
			  showAllArticles();
			  showAllPurchases();

			  // show the total
			  this->lblTotal->Caption = AnsiString().FormatFloat("0.00", shop->getTotalPrice());
		  }
		  else
		  {
              ShowError("Not enough stock!");
          }
		}
		else    // quantity is empty
		{
			ShowError("Please enter a quantity!"); //show error message
		}
	}
	else // stock item not selected
	{
		ShowError("Please select a stock item!");
	}
}
//---------------------------------------------------------------------------


void __fastcall TForm_Shop::btnRemoveClick(TObject *Sender)
{
	/*
	   1. remove button will remove item from purchase list and add back to stock list
	   2. reduce the total price
	*/

	int index = this->ListPurchase->ItemIndex;
	if (index != -1)   // if purchase item selected
	{
		if (!this->edtQuantity->Text.IsEmpty())// check edit quantity is not empty
		{
			/*
			   1. get purchase id
			   2. remove the purchase
			*/
			int id = shop->getPurchaseAtIndex(index)->getArticleID();	// get purchase id
			shop->unsoldSome(id, this->edtQuantity->Text.ToInt());

			// refresh listbox
			showAllArticles();
			showAllPurchases();

			// show the total
			this->lblTotal->Caption = AnsiString().FormatFloat("0.00", shop->getTotalPrice());
		}
		else    // quantity is empty
		{
			ShowError("Please enter a quantity!"); //show error message
		}
	}
	else // purchase item not selected
	{
		ShowError("Please select a purchase item!");
	}

}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::btnConfirmClick(TObject *Sender)
{
	/*
	   1. check if the user have enough credit to purchase
	   2. change the status label to success or not enough credit
	   3. update~the decrease balance of the guest in database
	   4. update~the decrease stcck list in database
	   5. clear the purchase list and customer id
	*/

	if (!this->edtGuestId->Text.IsEmpty())   // guest id is not empty
		{
			if (this->ListPurchase->Count > 0)   // purchase list is not empty
			{
				double balance;
				if (getBalance(this->edtGuestId->Text, balance) == true)
				{
					if (balance >= shop->getTotalPrice())
					{
						// update database
						decreaseStock();
						decreaseBalance(this->edtGuestId->Text, shop->getTotalPrice());

						// show confirmation
						ShowMessage("Purchase was succesfull!");

						// clear purchase
						shop->clearAllPuchases();

						// clear the gui
						this->ListPurchase->Clear();           // clear the purchase list
						this->edtQuantity->Clear();			   // clear the quantity
						this->edtGuestId->Clear();			   // clear the guest id
						this->lblTotal->Caption = "0.00";	   // reset the total price
					}
					else
					{
						ShowMessage("Not enough balance!");
					}
				}
				else
				{
                    ShowMessage("Guest ID not found!");
				}
			}
			else // purchase list is empty
			{
				ShowMessage("Purchase list is empty!");
			}
		}
		else // guest id is empty
		{
			ShowMessage("Please enter a Guest ID!");
		}
	}

//---------------------------------------------------------------------------

void __fastcall TForm_Shop::edtQuantityKeyPress(TObject *Sender, char &Key)
{
	// only allow 0-9 and backspace, also make sure value is higher than 0
	if (!((Key >= '0' && Key <= '9') || Key == VK_BACK))
	{
    	Key = 0;
	}
	else if (this->edtQuantity->Text.IsEmpty() && Key == '0')
	{
    	Key = 0;
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::btnCancelClick(TObject *Sender)
{
	// clear the purchase
	shop->unsoldAll();
	this->ListPurchase->Clear();

	// refresh listbox
	showAllArticles();

	// clear some labels and edit boxes
	this->edtQuantity->Clear();			   // clear the quantity
	this->edtGuestId->Clear();			   // clear the guest id
	this->lblTotal->Caption = "0.00";	   // reset the total price
	this->lblPurchaseInfo->Caption = "";   // reset the purchase info
}
//---------------------------------------------------------------------------
void __fastcall TForm_Shop::btnSortNameClick(TObject *Sender)
{
	// check if shop is created
	if (shop != NULL) {
    	// sort the artiles by name
        shop->sortAllArticlesByName();
	}
	showAllArticles(); 		// next we show the articles
}
//---------------------------------------------------------------------------
void __fastcall TForm_Shop::btnSortPriceClick(TObject *Sender)
{
	// check if shop is created
	if (shop != NULL) {
		// sort the artiles by price
		shop->sortAllArticlesBySalesValue();
	}
	showAllArticles(); 		// next we show the articles
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::btnSortKindClick(TObject *Sender)
{
	// check if shop is created
	if (shop != NULL) {
		// sort the artiles by kind
		shop->sortAllArticlesByKind();
	}
	showAllArticles(); 		// next we show the articles
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::ListOfStocksClick(TObject *Sender)
{
	// unselect the other list
	this->ListPurchase->ClearSelection();

	//update the correct info for the quanity
	updateInfo();
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::ListPurchaseClick(TObject *Sender)
{
	// unselect the other list
	this->ListOfStocks->ClearSelection();

	//update the correct info for the quanity
	updateInfo();
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::edtQuantityClick(TObject *Sender)
{
	this->edtQuantity->Text = "";	
}
//---------------------------------------------------------------------------

void __fastcall TForm_Shop::edtQuantityChange(TObject *Sender)
{
	//update the correct info for the quanity
	updateInfo();	
}
//---------------------------------------------------------------------------

